哈囉,各位邦友們!
昨天完成用事件綁定與 @for/@if 搭配 scss 來實現選中狀態時的互動。
今天來試著挑戰透過input編輯英雄名稱,並且在畫面上即時更新。
一、在 Standalone 中加入 FormsModule
// src/app/app.ts
// ...existing code...
import { FormsModule } from '@angular/forms';
// ...existing code...
@Component({
  // ...existing code...
  imports: [HeroBadge, FormsModule],
  // ...existing code...
})
export class App {
  // ...existing code...
  protected readonly heroes = signal<Hero[]>([
    { id: 11, name: 'Dr Nice', rank: 'B' },
    { id: 12, name: 'Narco', rank: 'A' },
    { id: 13, name: 'Bombasto' },
    { id: 14, name: 'Celeritas', rank: 'S' },
  ]);
  protected readonly selectedHero = signal<Hero | null>(null);
  // 新增:同步更新 selectedHero 與 heroes 清單
  updateName(name: string) {
    const selected = this.selectedHero();
    if (!selected) {
      return;
    }
    // 1. 建立更新後的英雄物件
    const updatedHero = { ...selected, name };
    // 2. 更新英雄列表 (heroes signal)
    this.heroes.update(list =>
      list.map(hero => (hero.id === updatedHero.id ? updatedHero : hero))
    );
    // 3. 更新當前選取的英雄 (selectedHero signal)
    this.selectedHero.set(updatedHero);
  }
}
二、用 ngModel 編輯選中英雄名稱並驗證
<!-- src/app/app.html -->
<!-- ...existing code... -->
<section>
  <!-- ...existing code... -->
  @if (selectedHero(); as s) {
    <aside class="panel">
      <h3>Selected</h3>
      <p>
        #{{ s.id }} - {{ s.name }}
        @if (s.rank) { <span class="rank">[{{ s.rank }}]</span> }
      </p>
      <label for="hero-name">Edit name:</label>
      <input
        id="hero-name"
        name="hero-name"
        type="text"
        placeholder="enter new name"
        required
        minlength="3"
        #nameCtrl="ngModel"
        [ngModel]="s.name"
        (ngModelChange)="updateName($event)"
        [attr.aria-invalid]="nameCtrl.invalid && nameCtrl.touched"
        aria-describedby="hero-name-errors" />
      @if (nameCtrl.invalid && nameCtrl.touched) {
        <ul id="hero-name-errors" class="errors">
          @if (nameCtrl.hasError('required')) {
            <li>請輸入名稱</li>
          }
          @if (nameCtrl.hasError('minlength')) {
            <li>至少 3 個字</li>
          }
        </ul>
      }
    </aside>
  }
</section>
<!-- ...existing code... -->
三、新增樣式
// src/app/app.scss
/* ...existing code... */
.errors {
  color: #c33;
}
驗收清單:
 
 
 
 
常見錯誤與排查:
今日小結:
今天在 Selected 區塊中加入 FormsModule 與 ngModel,使選取中的英雄可以編輯,並讓清單與選取畫面實現同步更新。
明天會將建立 HeroService,透過 inject() 依賴注入,學習Angular中服務的使用方法,讓專案更符合實際的架構設計。
參考資料: